可能想知道為什么要將文件“放入”數(shù)據庫,而不是僅僅放在文件系統(tǒng)上。那么大多數(shù)時候,你不會。
在您的PHP應用程序需要存儲整個文件的情況下,首選方法是將文件保存到服務器的文件系統(tǒng)中,并將文件的物理位置存儲在數(shù)據庫中。這通常被認為是存儲文件的最簡單和最快捷的方式。
但是,您可能會發(fā)現(xiàn)自己處于需要將文件與數(shù)據庫中其他數(shù)據保持一致的情況。這給你 - 或者說:MySQL - 完全控制文件數(shù)據,而不僅僅是文件在服務器上的位置。
這種方法有一些缺點,如:降低了性能,增加了PHP代碼和數(shù)據庫結構的復雜性。這是您在實際應用中使用之前應仔細考慮的內容。
話雖如此,本文演示了如何將文件從瀏覽器上傳到MySQL,以及如何將文件發(fā)送回瀏覽器。
開始之前
要順利完成,您應該熟悉以下內容:
PHP基礎知識
MySQL基礎知識
在PHP中使用MySQL(mysqli)
HTML表單以及如何在PHP中處理POST數(shù)據。
戰(zhàn)斗計劃
與所有計劃一樣,在我們開始撰寫之前,我們需要稍微計劃一點。所以我們知道我們在寫作之前要寫什么。
在開始該程序之前,我們需要設計數(shù)據庫。這不是一個復雜的設計,因為我們不是在說創(chuàng)建一些復雜的文件系統(tǒng)。我們只需要一個單獨的表格,其中包含一個用于我們文件的BLOB字段和各種其他字段來存儲我們文件中的信息,如名稱,大小,類型。
接著。該程序的第一階段是將文件從我們的用戶獲取到我們的PHP可以與它進行交互的服務器上。這是該過程中最簡單的部分,只需要一個基本的HTML表單。
第二階段涉及閱讀上傳的文件,確保已成功上傳并將其添加到數(shù)據庫。這與上傳文件到文件系統(tǒng)時使用的過程類似,但使用MySQL函數(shù)而不是文件系統(tǒng)函數(shù)。
第三階段是列出已經上傳并保存在數(shù)據庫中的所有文件,并附上一個鏈接,以便下載。這里唯一的問題是文件不存在于服務器上,所以我們如何創(chuàng)建一個鏈接呢?這是第4階段處理的一個問題,我們在階段3中需要做的是創(chuàng)建一個鏈接,該鏈接將嵌入到URL中的文件的ID。
第四個也是最后一部分是對這個過程最令人困惑的部分。我們獲取文件并將其發(fā)送到客戶端瀏覽器的部分。
我們從使用MySQL函數(shù)和第3階段發(fā)送的ID開始,從數(shù)據庫中獲取文件數(shù)據。然后我們設置幾個標題,讓瀏覽器知道預期的內容,最后發(fā)送文件的內容。
現(xiàn)在,以此摘要為指導,讓我們開始編寫我們的程序。
階段0:構建數(shù)據庫
數(shù)據庫很簡單。一個具有文件數(shù)據的BLOB字段的表和與文件相關的各種信息的幾個字段:
CREATE TABLE`file`(
`id` Int無符號不空Auto_Increment,
`name` VarChar(255)Not Null默認'Untitled.txt',
`mime` VarChar(50)Not Null默認'text / plain',
`size` BigInt Unsigned Not Null默認值0,
`data` MediumBlob不空,
`created` DateTime不空,
PRIMARY KEY(`id`)
)
如您所見,我們存儲文件名,包括擴展名。
我們有mime類型,我們使用它來讓瀏覽器知道我們正在處理什么樣的文件。
文件的大小(以字節(jié)為單位)。
最后數(shù)據本身在一個MediumBlob字段中。
階段1:上傳文件
現(xiàn)在,我們需要從用戶那里獲取文件。我們設計的表不需要用戶的任何其他信息,因此我們將簡單地創(chuàng)建一個HTML表單,只有一個“文件”輸入字段和提交按鈕:
<!DOCTYPE html>
<HEAD>
<title> MySQL文件上傳示例</ title>
<meta http-equiv=“content-type”content=“text / html; charset=UTF-8”>
</ HEAD>
<BODY>
<form action=“add_file.php”method=“post”enctype=“multipart / form-data”>
<input type=“file”name=“uploaded_file”> <br>
<input type=“submit”value=“Upload file”>
</ FORM>
<P>
<a href="list_files.php">查看所有文件</a>
</ p>
</ BODY>
</ HTML>
注意<form>元素的第三個屬性“enctype”。這告訴瀏覽器如何將表單數(shù)據發(fā)送到服務器。就這樣,當發(fā)送文件時,必須設置為“multipart / form-data”。
如果設置任何其他方式,或者根本不設置,您的文件可能不會被正確傳輸。
在底部,我們將鏈接到我們將在階段3中創(chuàng)建的列表。
階段2:將文件添加到數(shù)據庫
以我們在階段1中構建的形式,我們將action屬性設置為“add_file.php”。這是我們要在這個階段進行構建的文件。
此文件需要檢查文件是否已經上傳,確保已經上傳了沒有錯誤,并將其添加到數(shù)據庫中:
<?PHP
//檢查文件是否已上傳
if(isset($ _ FILES ['uploaded_file'])){
//確保文件被發(fā)送沒有錯誤
if($ _ FILES ['uploaded_file'] ['error']==0){
//連接到數(shù)據庫
$ dbLink=new mysqli('127.0.0.1','user','pwd','myTable');
if(mysqli_connect_errno()){
die(“MySQL連接失敗:”mysqli_connect_error());
}
//收集所有必需的數(shù)據
$ name=$ dbLink-> real_escape_string($ _ FILES ['uploaded_file'] ['name']);
$ mime=$ dbLink-> real_escape_string($ _ FILES ['uploaded_file'] ['type']);
$ data=$ dbLink-> real_escape_string(file_get_contents($ _ FILES ['uploaded_file'] ['tmp_name']));
$ size=intval($ _ FILES ['uploaded_file'] ['size']);
//創(chuàng)建SQL查詢
$ query=“
INSERT INTO`file`(
`name`,`mime`,`size`,`data`,````
)
值(
'{$ name}','{$ mime}',{$ size},'{$ data}',NOW()
)“;
//執(zhí)行查詢
$ result=$ dbLink-> query($ query);
//檢查是否成功
if($ result){
回應“成功!您的文件已成功添加!
}
else {
echo'錯誤!無法插入文件'
。“<PRE> {$ dbLink->誤差} </ PRE>”;
}
}
else {
echo'文件上傳時出錯。“
。'錯誤代碼: '。INTVAL($ _ FILES [ 'uploaded_file'] [ '錯誤']);
}
//關閉mysql連接
$ dbLink->接近();
}
else {
echo'錯誤!一個文件沒有發(fā)送!
}
//回到主頁面的鏈接
echo'<p>點擊<a href="index.html">此處</a>返回</ p>';
?>
階段3:列出所有現(xiàn)有文件
所以,現(xiàn)在我們在我們的數(shù)據庫中有幾個文件,我們需要創(chuàng)建一個文件列表并將它們鏈接起來,以便它們可以被下載:
<?PHP
//連接到數(shù)據庫
$ dbLink=new mysqli('127.0.0.1','user','pwd','myTable');
if(mysqli_connect_errno()){
die(“MySQL連接失敗:”mysqli_connect_error());
}
//查詢所有現(xiàn)有文件的列表
$ sql='SELECT`id`,`name`,`mime`,`size`,`created` FROM`file`';
$ result=$ dbLink-> query($ sql);
//檢查是否成功
if($ result){
//確保在那里有一些文件
if($ result-> num_rows==0){
echo'<p>數(shù)據庫中沒有文件</ p>';
}
else {
//打印表的頂部
echo'<table width=“100%”>
<TR>
<TD> <B>名稱</ B> </ TD>
<TD> <B>默</ B> </ TD>
<td> <b>大小(字節(jié))</ b> </ td>
<TD> <B>的創(chuàng)</ B> </ TD>
<TD> <B>&NBSP; </ B> </ TD>
</ TR>';
//打印每個文件
while($ row=$ result-> fetch_assoc()){
回聲“
<TR>
<TD> {$行[ '名稱']} </ TD>
<TD> {$行[ 'MIME']} </ TD>
<TD> {$行[ '尺寸']} </ TD>
<TD> {$行[ '創(chuàng)造']} </ TD>
<td> <a href='get_file.php?id={$row['id']}'>下載</a> </ td>
</ TR>“;
}
//關閉表
echo'</ table>';
}
//釋放結果
$ result->免費();
}
其他
{
echo'錯誤!SQL查詢失敗:';
echo“<pre> {$ dbLink-> error} </ pre>”;
}
//關閉mysql連接
$ dbLink->接近();
?>
階段4:下載文件
這部分是通常導致最混亂的部分。
要真正了解如何工作,您必須了解瀏覽器如何下載文件。當瀏覽器從HTTP服務器請求文件時,服務器響應將包含關于它所包含的內容的信息。這些信息位稱為標題。標題通常包括有關要發(fā)送的數(shù)據類型的信息,響應的大小以及文件的文件名稱。
當然有很多其他的標題,我不會在這里覆蓋,但值得研究!
現(xiàn)在,這段代碼。我們只需讀取第3階段鏈接發(fā)送的ID即可。如果ID有效,我們將獲取我們收到的ID的文件信息,發(fā)送頭文件,最后發(fā)送文件數(shù)據:
<?PHP
//確保已經通過了ID
if(isset($ _ GET ['id'])){
//獲取ID
$ id=intval($ _ GET ['id']);
//確保該ID實際上是一個有效的ID
if($ id <=0){
死('該ID無效!);
}
else {
//連接到數(shù)據庫
$ dbLink=new mysqli('127.0.0.1','user','pwd','myTable');
if(mysqli_connect_errno()){
die(“MySQL連接失敗:”mysqli_connect_error());
}
//獲取文件信息
$ query=“
SELECT`mime`,`name`,`size`,`data`
FROM`file`
WHERE`id`={$ id}“;
$ result=$ dbLink-> query($ query);
if($ result){
//確保結果有效
if($ result-> num_rows==1){
//獲取行
$ row=mysqli_fetch_assoc($ result);
//打印頭
header(“Content-Type:”。$ row ['mime']);
header(“Content-Length:”。$ row ['size']);
header(“Content-Disposition:attachment; filename=”。$ row ['name']);
//打印數(shù)據
echo $ row ['data'];
}
else {
echo'錯誤!沒有圖像存在該ID。
}
//釋放mysqli資源
@mysqli_free_result($結果);
}
else {
echo“錯誤!查詢失敗:<pre> {$ dbLink-> error} </ pre>”;
}
@mysqli_close($ DBLINK);
}
}
else {
echo'錯誤!沒有身份證通過。
}
?>
任何體面的瀏覽器都應該能夠讀取標題,并了解這是什么類型的文件,并且它是要下載的,而不是打開。
終點線
所以,正如你所看到的,這并不像人們想象的那么復雜。
這段代碼當然只是為了演示的目的,我不會建議使用它,而不增加一點額外的安全性。未經編輯,此代碼基本上允許任何人上傳任何內容到您的服務器,這不是一個好主意!
HP+JS實現(xiàn)大文件切片上傳功能實現(xiàn)實例源碼,PHP WEB開發(fā)——文件夾的上傳和下載,基于PHP+WEBUPLOADER的大文件分片上傳,支持斷點續(xù)傳,帶進度條,前端用了HTML,VUE2,VUE3,后端用了PHP,ThinkPHP,服務器用了Linux,數(shù)據庫是MySQL,上傳組件用的是百度的WebUploader,初期還是能用,但是下載這塊的話就不是很好用了,不太能滿足客戶的需求,
之前在網上也搜索過相關的資料,論壇上也有網友交流過,但是都不太令人滿意。這些文章和資料不能說毫無意義吧,只能說一文不值。離項目需求相差太遠。
這個是接的一個外包項目,客戶那邊是一個公司,給他們做的一個業(yè)務系統(tǒng)。
客戶要求能夠支持大文件下載,斷點續(xù)傳,批量下載,文件夾下載,文件夾下載要支持文件夾的層級結構,也就是用戶上傳的文件夾是什么層級結構,下載下來也必須是這個層級結構,項目一期我們是采用的打包的方式,直接在服務器上面把文件夾打成一個壓縮文件RAR,這樣下載下來后解壓,文件夾層級結構是一致的。
但是后來遇到一個問題,用戶上傳了一個文件夾,里面包含了1萬個文件,文件有大有小,大的有1G,10G,小的有幾KB,或者幾MB,將這個文件夾在服務器打包后變成了一個500G的文件。然后用戶下載這個文件的時候就崩潰了,用的是谷歌chrome,但是還是崩。版本:6.5.40
代碼:https://gitee.com/xproer/up6-php/tree/6.5.40/
安裝環(huán)境
PHP:7.2.14
調整塊大小
NOSQL
NOSQL不需要任何配置,可以直接訪問測試
SQL
創(chuàng)建數(shù)據庫
您可以直接復制腳本進行創(chuàng)建
配置數(shù)據庫連接
6.安裝依賴
訪問頁面進行測試
數(shù)據表中的數(shù)據
相關參考:
文件保存位置
php5教程,
源碼工程文檔:https://drive.weixin.qq.com/s?k=ACoAYgezAAw1dWofra
源碼報價單:https://drive.weixin.qq.com/s?k=ACoAYgezAAwoiul8gl
OEM版報價單:https://drive.weixin.qq.com/s?k=ACoAYgezAAwuzp4W0a
控件源碼下載:https://drive.weixin.qq.com/s?k=ACoAYgezAAwbdKCskc
EB中實現(xiàn)文件上傳下載的三種解決方案(推薦),WEB開發(fā)——文件的上傳和下載,B/S WEB怎么實現(xiàn)大文件上傳,完美解決JAVA無法上傳大文件方法,Java實戰(zhàn):大文件分片上傳與斷點續(xù)傳策略及其實際應用,JAVA大文件上傳(秒傳、分片上傳、斷點續(xù)傳),JAVA實現(xiàn)大文件的分片上傳與下載,JAVA實現(xiàn)文件上傳和下載的方法詳解,
SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(文檔),SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(視頻),
SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(教程),SPRINGCLOUD中實現(xiàn)文件加密上傳下載的三種解決方案(推薦),
php中實現(xiàn)文件上傳下載的三種解決方案(推薦),.net mvc中實現(xiàn)文件上傳下載的三種解決方案(推薦),.net core中實現(xiàn)文件上傳下載的三種解決方案(推薦),.net中實現(xiàn)文件上傳下載的三種解決方案(推薦),asp.net中實現(xiàn)文件上傳下載的三種解決方案(推薦),
input file中實現(xiàn)文件上傳下載的三種解決方案(推薦),dom中實現(xiàn)文件上傳下載的三種解決方案(推薦),vue中實現(xiàn)文件上傳下載的三種解決方案(推薦),網頁中實現(xiàn)文件上傳下載的三種解決方案(推薦),前端中實現(xiàn)文件上傳下載的三種解決方案(推薦),
百度webuploader中實現(xiàn)文件上傳下載的三種解決方案(推薦),webuploader中實現(xiàn)文件上傳下載的三種解決方案(推薦),jsp中實現(xiàn)文件上傳下載的三種解決方案(推薦),java中實現(xiàn)文件上傳下載的三種解決方案,
SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(源碼),SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(源代碼),SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(代碼),SPRINGCLOUD中實現(xiàn)文件上傳下載的三種解決方案(推薦),java如何實現(xiàn)大文件斷點續(xù)傳、秒傳,JAVA實現(xiàn)文件上傳到服務器,jsp實現(xiàn)文件上傳到服務器,SpringBoot實現(xiàn)文件上傳到服務器,SpringMVC實現(xiàn)文件上傳到服務器,SpringCloud實現(xiàn)文件上傳到服務器,
webuploader實現(xiàn)文件上傳到服務器,百度webuploader實現(xiàn)文件上傳到服務器,JAVA如何將文件上傳到服務器,html5實現(xiàn)文件上傳到服務器,html實現(xiàn)文件上傳到服務器,vue實現(xiàn)文件上傳到服務器,JavaScript實現(xiàn)文件上傳到服務器,js實現(xiàn)文件上傳到服務器,前端實現(xiàn)文件上傳到服務器,網頁實現(xiàn)文件上傳到服務器,web實現(xiàn)文件上傳到服務器,dom實現(xiàn)文件上傳到服務器,input file實現(xiàn)文件上傳到服務器,JAVA實現(xiàn)文件分片上傳到服務器,
webuploader實現(xiàn)文件分片上傳到服務器,html5實現(xiàn)文件分塊上傳到服務器,百度webuploader實現(xiàn)文件分割上傳到服務器,百度webuploader實現(xiàn)文件切割上傳到服務器,html5實現(xiàn)文件切片上傳到服務器,JAVA實現(xiàn)文件上傳秒傳到服務器,
后端的話支持多種語言,比如ASP.NET,JSP,PHP,GO等,這個是沒有限制的,前端主要是通過相關的接口與后端進行交互。
之前在網上也找過相關的資料,論壇里面也有網友交流過,還加過很多QQ群和微信群,但是結果都不太令人滿意,
很網文章里面都只討論了上傳,基本上全部都是用的HTML5提供的API,但是沒有講下載,用戶這塊是有下載的需求。
B/S WEB端,也就是前端,網頁端,不是指后端,看很多網上的文章都在寫后端,后端用戶沒法用啊,也選不了文件。
應該說還是比較完美的,幾個方面吧,一個是強大的兼容性,能夠兼容所有瀏覽器,包括IE瀏覽器,另一個是能夠支持信創(chuàng)國產化
網上文章基本上全部都說的是調用HTML5的API來實現(xiàn),但是這個我們也試過,兼容性不行,不能支持IE,
java大文件10G,50G,100G上傳下載,JSP大文件10G,50G,100G上傳下載,JAVA大文件10G,50G,100G上傳下載,斷點續(xù)傳。
一般這么大的文件不用HTML的一次性上傳,而是采用分塊,分片,分段,分割,切割技術上傳。
JAVA話一般是負責后端的邏輯,比如文件初始化,文件塊上傳,合并,存儲等。
前端的話用JSP,VUE2,VUE3,React,HTML5,JS,JQ都行。這個都無所謂。
網上一般的做法都是用的HTML5的API,也就是chrome提供的API,能夠滿足基本需求,但是還是有痛點,chrome限制死了,固定死了無法擴展,每個域名只允許5個TCP連接,導致了速度有上限,你也無法修改和擴展。然后就是瀏覽器也只能用chrome,用戶用了IE就不行了,用戶現(xiàn)有的系統(tǒng)跑在IE上,也不能換。
進度信息容易丟失,用戶關閉網頁,刷新網頁,關閉瀏覽器,重啟瀏覽器,關閉電腦,重啟電腦后,進度信息都會丟失,無解,沒辦法。擴展性還是差了點。
傳大文件,超大文件,文件數(shù)量多的話,前端就卡,網頁反應慢,容易死,崩潰,在配置較差的電腦或者配置一般的電腦上這個痛點體現(xiàn)的非常明顯。
下載,網上找到的資料一般都是講上傳的,很少講下載的。
視頻教程:https://www.ixigua.com/7227314770696012322
導入項目:
導入到Eclipse:http://www.ncmem.com/doc/view.aspx?id=9da9c7c2b91b40b7b09768eeb282e647
導入到IDEA:http://www.ncmem.com/doc/view.aspx?id=9fee385dfc0742448b56679420f22162
springboot統(tǒng)一配置:http://www.ncmem.com/doc/view.aspx?id=7768eec9284b48e3abe08f032f554ea2
下載示例:
https://gitee.com/xproer/up6-jsp-eclipse/tree/6.5.40/
工程
NOSQL
NOSQL示例不需要任何配置,可以直接訪問測試
創(chuàng)建數(shù)據表
選擇對應的數(shù)據表腳本,這里以SQL為例
修改數(shù)據庫連接信息
訪問頁面進行測試
文件存儲路徑
up6/upload/年/月/日/guid/filename
相關問題:
1.javax.servlet.http.HttpServlet錯誤
2.項目無法發(fā)布到tomcat
3.md5計算完畢后卡住
4.服務器找不到config.json文件
相關參考:
文件保存位置
源碼工程文檔:https://drive.weixin.qq.com/s?k=ACoAYgezAAw1dWofra
源碼報價單:https://drive.weixin.qq.com/s?k=ACoAYgezAAwoiul8gl
OEM版報價單:https://drive.weixin.qq.com/s?k=ACoAYgezAAwuzp4W0a
產品源代碼:https://drive.weixin.qq.com/s?k=ACoAYgezAAwbdKCskc
授權生成器:https://drive.weixin.qq.com/s?k=ACoAYgezAAwTIcFph1
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。