iT邦幫忙

1

PHP檔案上傳docx轉base64問題

檔案上傳以往都會用move_uploaded_file將檔案搬至對應資料夾

不過我想將檔案編碼後放在資料庫裡面

於是用了base64_encodefile_get_contents來處理

任何檔案上傳測試都成功(jpg.png.gif.pdf.xls.doc.zip....)

不過當我測到docx檔時

確實是編碼成功~

也可以讓我echo成連結供人下載

但是下載下來的檔案卻變成壓縮檔

解壓後是一堆xml檔與資料夾

我一查才知道..原來docx本身是壓縮檔..將副檔名改成zip解壓後..就跟我現在看到的樣子一樣

echo "檔案類型: " . $_FILES["file"]["type"];

我比較了一下doc的type

doc長這樣application/msword

docx長這樣application/vnd.openxmlformats-officedocument.wordprocessingml.document

這樣的狀況該怎麼處理

我像讓使用者下載下來是一個可以正常以WORD開啟的docx檔案

以下提供我測試用的程式:
test.html

<html>
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
</head>
<body>
    <form action="php/upload.php" method="post" enctype="multipart/form-data">
        選擇檔案:<input type="file" name="file" id="file" /><br />
        <input type="submit" name="submit" value="上傳檔案" />
    </form>
</body>
</html> 

upload.php

<?php 
header("Content-Type:text/html; charset=utf-8");
if ($_FILES["file"]["error"] > 0){ 
    echo "Error: " . $_FILES["file"]["error"]; 
} else {
    echo "檔案名稱: " . $_FILES["file"]["name"]."<br/>"; 
    echo "檔案類型: " . $_FILES["file"]["type"]."<br/>";
    echo "檔案大小: " . ($_FILES["file"]["size"] / 1024)." Kb<br />";
    echo "暫存名稱: " . $_FILES["file"]["tmp_name"]."<br/>"; 
    echo "<a href='"."data:".$_FILES["file"]["type"].";base64,".base64_encode(file_get_contents($_FILES['file']['tmp_name']))."'>".$_FILES["file"]["name"]."</a>";
}
?>
看更多先前的討論...收起先前的討論...
weiclin iT邦高手 4 級 ‧ 2018-01-18 14:33:17 檢舉
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
weiclin
不好意思~
我看不太懂..==
我補上我程式碼了
你提供的那段我要放哪==

我有試過放upload.php
我按上傳會叫我下載upload.php
weiclin iT邦高手 4 級 ‧ 2018-01-18 14:44:35 檢舉
當然是放在下載的那邊啊, 在你 "echo成連結供人下載" 那個地方
>當然是放在下載的那邊

我這樣放
<?php
header("Content-Type:text/html; charset=utf-8");
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
if ($_FILES["file"]["error"] > 0){
echo "Error: " . $_FILES["file"]["error"];
} else {
echo "檔案名稱: " . $_FILES["file"]["name"]."<br/>";
echo "檔案類型: " . $_FILES["file"]["type"]."<br/>";
echo "檔案大小: " . ($_FILES["file"]["size"] / 1024)." Kb<br />";
echo "暫存名稱: " . $_FILES["file"]["tmp_name"]."<br/>";
echo "<a href='"."data:".$_FILES["file"]["type"].";base64,".base64_encode(file_get_contents($_FILES['file']['tmp_name']))."'>".$_FILES["file"]["name"]."</a>";
}
?>

我按上傳會叫我下載upload.php
我供人下載 是直接echo一串<a> tag
href 就是檔案轉成的base64編碼
weiclin iT邦高手 4 級 ‧ 2018-01-18 15:26:45 檢舉
你有沒有發現你送出兩個 Content-Type ?
如果是這樣弄的話, 看下面的回答吧
您給我一串字串時
我就有疑惑了~
試過後..跟預期一樣..
所以還是不懂
現在是以你提供的這串去搜尋相關資訊..= =
我看懂了...
你是要我導到另一頁執行..

如果是這樣的話..
這招行不通

因為我最終瀏覽的頁面
會有各式的檔案類型
這樣等於鎖死這頁網頁只能以application/vnd.openxmlformats-officedocument.wordprocessingml.document開啟

再者..
我目的要讓使用者下載檔案(附件)
沒要讓使用者直接在網頁上預覽檔案(例如PDF)
weiclin iT邦高手 4 級 ‧ 2018-01-18 15:53:05 檢舉
那你試試這個吧, 當然, 是導到另一頁執行的
header('Content-type: application/octet-stream; charset=utf-8');
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

1
石頭
iT邦高手 1 級 ‧ 2018-01-18 15:23:58
最佳解答
  echo "<a href='"."data:".$_FILES["file"]["type"].";base64,".base64_encode(file_get_contents($_FILES['file']['tmp_name']))."'>".$_FILES["file"]["name"]."</a>";

改成

  echo "<a href='data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,".base64_encode(file_get_contents($_FILES['file']['tmp_name']))."'>".$_FILES["file"]["name"]."</a>";

PS: Content-Type 告訴瀏覽器要怎麼處理接收的資料..

建議可以導到另一頁PHP,在做下載動作

看更多先前的回應...收起先前的回應...

這...未改之前
$_FILES["file"]["type"]出來的字串就是application/vnd.openxmlformats-officedocument.wordprocessingml.document

您回答的答案..
只是把data後面那段寫死而已耶~~0..0

石頭 iT邦高手 1 級 ‧ 2018-01-18 15:32:32 檢舉

你可以做程式判斷...
我只是拋磚引玉 且我也不知道你的需求是什麼@@

我知道您在引導思考方向
所以我還在思考
我的回復只是提出疑惑~XD

我的需求
就是把各種檔案都變成base64資料
好讓我存進資料庫
(無論是圖檔.文件檔.PDF檔.壓縮檔...等等)
日後..
在瀏覽頁面將資料撈出來
可以用<a> tag變成連結
像是一般常見的附件檔下載一樣
或是說如同E-mail的附件下載一樣
(我有發現E-mail的附件也是採這種方式呈現)

我上面提供的程式碼test.html與upload.php
是我測試用的
可以直接複製來玩

而最後一行echo
則是模擬當我從資料庫撈出這串base64後
<a> tag組合產生的結果

經過dog830228的PS提示
我看懂weiclin一開始提供的答案要幹嘛了..
你是要我導到另一頁執行..

如果是這樣的話..
這招行不通

因為我最終瀏覽的頁面
會有各式的檔案類型
這樣等於鎖死這頁網頁只能以application/vnd.openxmlformats-officedocument.wordprocessingml.document開啟

再者..
我目的要讓使用者下載檔案(附件)
沒要讓使用者直接在網頁上預覽檔案(例如PDF)

PS..
我的測試程式碼
自己測過後
可以上傳全部檔案

而echo出來的連結
也都可以讓我下載檔案
也可以正常開啟

唯獨docx雖說可以下載
但下載下來卻是一份壓縮檔
而不是我原本上傳的docx檔

我有將壓縮檔強制以word打開
卻可以正常開啟
內容也與原上傳檔案一樣

石頭 iT邦高手 1 級 ‧ 2018-01-18 15:56:26 檢舉

如果需求是把檔案內容存base64到資料庫
可以再多存一個欄位這個檔案的Content-Type
(存入Content-Type欄位前,你要再程式那邊做判斷)

例如:docx不能正常開啟,你可在程式判斷副檔名或是其他資訊把Content-Type存成application/vnd.openxmlformats-officedocument.wordprocessingml.document

等使用者要下載時 在告訴Header這個檔案的格式

看你是要在A Tag直接做調還是要在另一個頁面做都可以

但我建議轉導到另一個頁面

解決了
我在a tag加了這段 download=".$_FILES["file"]["name"]."
讓使用者下載時強制自動命名檔案名稱和副檔名
$_FILES["file"]["name"]這串
取得的正是原本的檔案名稱加原始副檔名..

石頭 iT邦高手 1 級 ‧ 2018-01-18 17:36:30 檢舉

/images/emoticon/emoticon12.gif

0
haoming
iT邦好手 1 級 ‧ 2018-01-18 16:16:12

之前有段時間 apache, iis 在 一開始 不認識 docx 的檔案
都要去修改 mime.types 內容
加上這個

AddType  application/vnd.openxmlformats  .docx .pptx .xlsx .xltx . xltm .dotx .potx .ppsx

或者加在 .htaccess 也可以

http://www.freetutorialssubmit.com/apache-mime-type-configuration-to-open-docx-pptx-xlsx-ms-office-files/1436

我要發表回答

立即登入回答