Liệu Hàm URLDownloadToFile có thể tải file về khi đường dẫn có chuỗi Unicode? (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

phan ngoc lan

Phan ngọc lan(^_^)
Tham gia
10/6/10
Bài viết
145
Được thích
340
Nghề nghiệp
Xây dựng
Chào các anh/chị và các thầy trên diễn đàn hiện em đang viết một file có tải một số bức ảnh, hay source code của trang Web nhưng chỉ tải được khi đường dẫn tải về không có chứa chuỗi Unicode. Khi em chuyển đường dẫn về chuỗi có chứa Unicode thì không tải được. Mong mọi người chỉ giúp liệu có tải file về theo đường dẫn có chứa chuỗi Unicode được không? và có cách nào để mình biết tốc độ tải file về không.
Em dùng hàm:
PHP:
Private Declare Function URLDownloadToFile Lib "urlmon" Alias _
                                "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
                                ByVal szFileName As String, ByVal dwReserved As Long, _
                                ByVal lpfnCB As Long) As Long

Public Function DownLoadfile(sSourceUrl As String, sLocalFile As String) As Boolean

        DownLoadfile = URLDownloadToFile(0&, sSourceUrl, sLocalFile, BINDF_GETNEWESTVERSION, 0&) = ERROR_SUCCESS

End Function
 
Chào các anh/chị và các thầy trên diễn đàn hiện em đang viết một file có tải một số bức ảnh, hay source code của trang Web nhưng chỉ tải được khi đường dẫn tải về không có chứa chuỗi Unicode. Khi em chuyển đường dẫn về chuỗi có chứa Unicode thì không tải được. Mong mọi người chỉ giúp liệu có tải file về theo đường dẫn có chứa chuỗi Unicode được không? và có cách nào để mình biết tốc độ tải file về không.
Em dùng hàm:
PHP:
Private Declare Function URLDownloadToFile Lib "urlmon" Alias _
                                "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
                                ByVal szFileName As String, ByVal dwReserved As Long, _
                                ByVal lpfnCB As Long) As Long

Public Function DownLoadfile(sSourceUrl As String, sLocalFile As String) As Boolean

        DownLoadfile = URLDownloadToFile(0&, sSourceUrl, sLocalFile, BINDF_GETNEWESTVERSION, 0&) = ERROR_SUCCESS

End Function

Bạn hãy dùng URLDownloadToFileW.
Bạn hãy nghiên cứu thông số cuối cùng. Nó là interface IBindStatusCallback
 
Bạn hãy dùng URLDownloadToFileW.
Bạn hãy nghiên cứu thông số cuối cùng. Nó là interface IBindStatusCallback
cảm ơn thầy đã hướng dẫn nhưng về các hàm Api em chỉ biết gà mờ thôi theo hàm URLDownloadToFileW của thầy em lắp đủ kiểu, rồi tới tìm trên mạng nhưng vẫn không thành công. Mong thầy chỉ rõ hàm và cho ví dụ cụ thể. Em xin cảm ơn!
 
cảm ơn thầy đã hướng dẫn nhưng về các hàm Api em chỉ biết gà mờ thôi theo hàm URLDownloadToFileW của thầy em lắp đủ kiểu, rồi tới tìm trên mạng nhưng vẫn không thành công. Mong thầy chỉ rõ hàm và cho ví dụ cụ thể. Em xin cảm ơn!

Trước tiên ta thống nhất với nhau là cứ gọi "bạn" thôi nhé.
Bạn có khúc mắc ở khâu nào? Tôi từ xưa tới nay chỉ dùng URLDownloadToFileA nhưng trong thư viện có cả URLDownloadToFileW.
Về thông số cuối cùng thì vd. trong Delphi phải có class implement interface IBindStatusCallback. Class phải implement tất cả các method của interface. Hàm sẽ dùng interface này để gọi các method của interface (nếu truyền nil (trong Delphi), 0 thì thôi). Trong VBA thì chắc phải là insert Class. Dưới đây là code để bạn tham khảo. Nó chỉ mới được viết chứ chưa thử nghiệm. Mục đích để bạn có chút hướng đi. Mà bạn phải chắc chắn là truyền Unicode đấy nhé. Cái String trong VBA nó hơi bị rắc rối, rồi vbUnicode với vbFromUnicode, lắm chuyện.
PHP:
Option Explicit
' ClassForCallBack
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileW" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Implements olelib.IBindStatusCallback
Public Function DownloadFile(ByVal URL As String, ByVal LocalFile As String) As Long
 DownloadFile = olelib.URLDownloadToFile(0&, URL, LocalFile, 0, Me)
End Function
Private Sub IBindStatusCallback_GetBindInfo(grfBINDF As olelib.BINDF, pbindinfo As olelib.BINDINFO)
 DoEvents
End Sub
Private Function IBindStatusCallback_GetPriority() As Long
End Function
Private Sub IBindStatusCallback_OnDataAvailable(ByVal grfBSCF As olelib.BSCF, ByVal dwSize As Long, pformatetc As olelib.FORMATETC, pStgmed As olelib.STGMEDIUM)
End Sub
Private Sub IBindStatusCallback_OnLowResource(ByVal reserved As Long)
End Sub
Private Sub IBindStatusCallback_OnObjectAvailable(riid As olelib.UUID, ByVal pUnk As stdole.IUnknown)
End Sub
Private Sub IBindStatusCallback_OnProgress(ByVal ulProgress As Long, ByVal ulProgressMax As Long, ByVal ulStatusCode As olelib.BINDSTATUS, ByVal szStatusText As Long)
 Debug.Print Format((ulProgress / ulProgressMax), "0.00%")
End Sub
Private Sub IBindStatusCallback_OnStartBinding(ByVal dwReserved As Long, ByVal pib As olelib.IBinding)
 DoEvents
End Sub
Private Sub IBindStatusCallback_OnStopBinding(ByVal hresult As Long, ByVal szError As Long)
 DoEvents
End Sub
--------------
Public Sub download()
Dim obj As ClassForCallBack
Dim result As Long
Set obj = New ClassForCallBack
result = obj.DownloadFile("http://www....", "c:\temp\...")
Select Case result
 Case S_OK
  MsgBox "..."
 Case E_ABORT
  MsgBox "..."
 Case Else
  MsgBox "..."
End Select
End Sub
 
trong phần hướng dẫn của thầy:
Code em cho vào classmodule:
PHP:
Option Explicit
 ClassForCallBack
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileW" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Implements olelib.IBindStatusCallback
Public Function DownloadFile(ByVal URL As String, ByVal LocalFile As String) As Long
 DownloadFile = olelib.URLDownloadToFile(0&, URL, LocalFile, 0, Me)
End Function
Private Sub IBindStatusCallback_GetBindInfo(grfBINDF As olelib.BINDF, pbindinfo As olelib.BINDINFO)
 DoEvents
End Sub
Private Function IBindStatusCallback_GetPriority() As Long
End Function
Private Sub IBindStatusCallback_OnDataAvailable(ByVal grfBSCF As olelib.BSCF, ByVal dwSize As Long, pformatetc As olelib.FORMATETC, pStgmed As olelib.STGMEDIUM)
End Sub
Private Sub IBindStatusCallback_OnLowResource(ByVal reserved As Long)
End Sub
Private Sub IBindStatusCallback_OnObjectAvailable(riid As olelib.UUID, ByVal pUnk As stdole.IUnknown)
End Sub
Private Sub IBindStatusCallback_OnProgress(ByVal ulProgress As Long, ByVal ulProgressMax As Long, ByVal ulStatusCode As olelib.BINDSTATUS, ByVal szStatusText As Long)
 Debug.Print Format((ulProgress / ulProgressMax), "0.00%")
End Sub
Private Sub IBindStatusCallback_OnStartBinding(ByVal dwReserved As Long, ByVal pib As olelib.IBinding)
 DoEvents
End Sub
Private Sub IBindStatusCallback_OnStopBinding(ByVal hresult As Long, ByVal szError As Long)
 DoEvents
End Sub
--------------
nhưng nó báo lỗi khi khi chạy code tại dòng: Implements olelib.IBindStatusCallback
nên vẫn chưa được liệu file có phải tham chiếu vào thư viện nào không thầy?
 
trong phần hướng dẫn của thầy:
Code em cho vào classmodule:
PHP:
Option Explicit
 ClassForCallBack
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileW" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Implements olelib.IBindStatusCallback
Public Function DownloadFile(ByVal URL As String, ByVal LocalFile As String) As Long
 DownloadFile = olelib.URLDownloadToFile(0&, URL, LocalFile, 0, Me)
End Function
Private Sub IBindStatusCallback_GetBindInfo(grfBINDF As olelib.BINDF, pbindinfo As olelib.BINDINFO)
 DoEvents
End Sub
Private Function IBindStatusCallback_GetPriority() As Long
End Function
Private Sub IBindStatusCallback_OnDataAvailable(ByVal grfBSCF As olelib.BSCF, ByVal dwSize As Long, pformatetc As olelib.FORMATETC, pStgmed As olelib.STGMEDIUM)
End Sub
Private Sub IBindStatusCallback_OnLowResource(ByVal reserved As Long)
End Sub
Private Sub IBindStatusCallback_OnObjectAvailable(riid As olelib.UUID, ByVal pUnk As stdole.IUnknown)
End Sub
Private Sub IBindStatusCallback_OnProgress(ByVal ulProgress As Long, ByVal ulProgressMax As Long, ByVal ulStatusCode As olelib.BINDSTATUS, ByVal szStatusText As Long)
 Debug.Print Format((ulProgress / ulProgressMax), "0.00%")
End Sub
Private Sub IBindStatusCallback_OnStartBinding(ByVal dwReserved As Long, ByVal pib As olelib.IBinding)
 DoEvents
End Sub
Private Sub IBindStatusCallback_OnStopBinding(ByVal hresult As Long, ByVal szError As Long)
 DoEvents
End Sub
--------------
nhưng nó báo lỗi khi khi chạy code tại dòng: Implements olelib.IBindStatusCallback
nên vẫn chưa được liệu file có phải tham chiếu vào thư viện nào không thầy?

Thú thực là tôi chưa dùng callback bao giờ - tôi khuyên bạn nghiên cứu là vì thế. Nhưng trong Delphi tôi nghĩ là đơn giản vì interface IBindStatusCallback được định nghĩa trong urlmon, chỉ việc có class implement IBindStatusCallback là đã có thể thử nghiệm xem thế nào. Nhưng urlmon.dll không thêm được vào tham chiếu. Code trên là "cố lái" vào VBA. Bạn xem trong máy có olelib.tlb không thì thử tham chiếu.
Hiện nay tôi cũng hơi bận nên chưa thể thử nghiệm được.
 
Chào các anh/chị và các thầy trên diễn đàn hiện em đang viết một file có tải một số bức ảnh, hay source code của trang Web nhưng chỉ tải được khi đường dẫn tải về không có chứa chuỗi Unicode. Khi em chuyển đường dẫn về chuỗi có chứa Unicode thì không tải được. Mong mọi người chỉ giúp liệu có tải file về theo đường dẫn có chứa chuỗi Unicode được không?
Bạn thử cho 1 đường link có chuổi Unicode để tôi thí nghiệm thử xem
 
Bạn thử cho 1 đường link có chuổi Unicode để tôi thí nghiệm thử xem
Dạ không thưa thầy ý em là tải file trên Web về máy, mà đường dẫn của file mình sẽ lưu trên máy có ký tự chứa Unicode(chứ ko phải đường link có chuổi Unicode) mong thầy chỉ bảo. Em cảm ơn thầy!
 
Download bằng hàm URLDownloadToFile với chuỗi unicode

Tôi gửi bạn ví dụ đơn giản về download. Hàm DownloadFile cho phép sử dụng chuỗi unicode.

Tạo một module rồi chép các đoạn code dưới đây:
Mã:
Option Explicit

Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileW" (ByVal pCaller As Long, _
                                                                                    ByVal szURL As String, _
                                                                                    ByVal szFileName As String, _
                                                                                    ByVal dwReserved As Long, _
                                                                                    ByVal lpfnCB As Long) As Long

Public Function DownloadFile(ByVal URL As String, _
                             ByVal LocalFilename As String) As Boolean
    Dim lngRetVal As Long
     
    lngRetVal = URLDownloadToFile(0, StrConv(URL, vbUnicode), StrConv(LocalFilename, vbUnicode), 0, 0)
    If lngRetVal = 0 Then DownloadFile = True
End Function
[COLOR="#008000"]'Test[/COLOR]
Private Sub TestDownload()
[COLOR="#008000"]    'Range("B2") --- đường dẫn trên mạng
    'Range("B3") --- file lưu.[/COLOR]
    If DownloadFile(Range("B2"), Range("B3")) Then
        MsgBox "Da dowwnload thanh cong."
    Else
        MsgBox "Loi dowwnload."
    End If
End Sub

Lưu ý: từ Windows Vista trở lên, thư mục để lưu file phải được thiết lập quyền được ghi. Để test ví dụ này bạn có thể chọn lưu về một địa chỉ trên Desktop.

Để hoàn thiện hơn phải sử dụng tham số lpfnCB trong hàm URLDownloadToFile, tham số này giúp ta kiểm soát tiến trình download. Tôi bận chưa có time để nghiên cứu tiếp cách dùng tham số này.
 

File đính kèm

Cảm ơn thầy vậy mà em cứ hì hụi mãi mà không được:-=. Em đã test và tải thành công!. Mong thầy có nhiều sức khoẻ và có nhiều thời gian hơn để chỉ bảo cánh "Gà mờ" chúng em về VBA
 
Lần chỉnh sửa cuối:
Thú thực là tôi chưa dùng callback bao giờ - tôi khuyên bạn nghiên cứu là vì thế. Nhưng trong Delphi tôi nghĩ là đơn giản vì interface IBindStatusCallback được định nghĩa trong urlmon, chỉ việc có class implement IBindStatusCallback là đã có thể thử nghiệm xem thế nào. Nhưng urlmon.dll không thêm được vào tham chiếu. Code trên là "cố lái" vào VBA. Bạn xem trong máy có olelib.tlb không thì thử tham chiếu.
Hiện nay tôi cũng hơi bận nên chưa thể thử nghiệm được.

Về unicode thì tôi đã nói - ta dùng hàm W.
Về điều khiển quá trình download thì tôi cũng đã nói - đó là thông số cuối cùng. Chỉ có điều ...
Tôi cũng không có olelib.tlb, nhưng tôi tìm thấy trên mạng (không phải phiên bản nào cũng dùng được)
Các bước:
1. Bạn tải về tập tin tôi đính kèm --> giải nén --> sao chép olelib.tlb vào thư mục Windows\System32 (tôi dùng XP). Tâp tin thứ 2 là ví dụ urldownload.xls. Bạn mở xls --> vào VBA --> Tools --> references --> browse ... --> duyệt tới olelib.tlb trong System32 --> OK
2. Code vẫn như cũ, nhưng đề phòng nếu có chút khác đi thì tôi đính kèm luôn urldownload.xls.
À có khác chút: Ta gọi UrlDownloadToFile trong olelib chứ không khai báo.
 

File đính kèm

Cảm ơn thầy vậy mà em cứ hì hụi mãi mà không được:-=. Em đã test và tải thành công!. Mong thầy có nhiều sức khoẻ và có nhiều thời gian hơn để chỉ bảo cánh "Gà mờ" chúng em về VBA

Tôi không hiểu bạn lắm. Bạn đã dùng được URLDownloadToFileA thì sao bạn lại không biết dùng URLDownloadToFileW? Chỉ có mỗi khác là phải truyền string unicode, thế thôi. Do trong VBA rắc rối nên tôi đã lưu ý. Nếu đã có unicode rồi thì thôi, còn nếu lấy từ sheet thì phải convert (vbUnicode). Tôi đã lưu ý bạn rồi mà. Cái chuyện vbFromUnicode và vbUnicode bạn làm mãi rồi còn gì?
 
Em xin cảm ơn thầy đã giành thời gian giúp đỡ! .File của thầy rất chuẩn có thể tải về theo đường dẫn có chứa chuỗi Unicode và thể hiện được tốc độ phần trăm Download của file. Em xin cảm ơn! chắc tới chiều em sẽ gửi lên diễn đàn file:(thành quả lao động mấy hôm nay của em--=0)

Tôi không hiểu bạn lắm. Bạn đã dùng được URLDownloadToFileA thì sao bạn lại không biết dùng URLDownloadToFileW? Chỉ có mỗi khác là phải truyền string unicode, thế thôi. Do trong VBA rắc rối nên tôi đã lưu ý. Nếu đã có unicode rồi thì thôi, còn nếu lấy từ sheet thì phải convert (vbUnicode). Tôi đã lưu ý bạn rồi mà. Cái chuyện vbFromUnicode và vbUnicode bạn làm mãi rồi còn gì?
Hì Hì! Em chỉ biết viết code VBA thôi chứ về mấy cái Hàm API thì em chịu!!!:=\+

Mà hầu như các code em chỉ biết copy và thay thế thôi!
(P/S: việc Cái chuyện vbFromUnicode và vbUnicode giờ thầy nói em mới để ý. Đúng là cái này em gặp quá nhiều trong các đoạn mã rồi. Đúng là đoảng quá)
 
Chỉnh sửa lần cuối bởi điều hành viên:
Để đơn giản hóa vấn đề, tôi có cách này:
- Download file về 1 Temp Folder
- Dời file từ Temp Folder đến folder ta cần
1> Các hàm API hổ trợ:
PHP:
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _
  (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, _
   ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" _
  (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Const MAX_PATH = 260
2> Get Temp Folder
PHP:
Private Function GetTmpPath()
  Dim sFolder As String ' Name of the folder
  Dim lRet As Long ' Return Value
  sFolder = String(MAX_PATH, 0)
  lRet = GetTempPath(MAX_PATH, sFolder)
  If lRet <> 0 Then
    GetTmpPath = Left(sFolder, InStr(sFolder, _
    Chr(0)) - 1)
  Else
    GetTmpPath = vbNullString
  End If
End Function
3> Download và di chuyển File
Mã:
Sub Test()
  Dim sUrl As String, sSave As String, sTmpPath As String
  sTmpPath = GetTmpPath & "tên file"  ''Ví dụ  [B]GetTmpPath & "tmp.jpg[/B]"
  sUrl = "Dia chi Url"
  sSave = "Duong dan file lưu"    ''---> Ví dụ:[B] sSave = Range("A2").Value[/B] với cell A2 chứa chuổi[B] D:\Anh Tuấn\tmp.jpg[/B]
  If URLDownloadToFile(0&, sUrl, sTmpPath, &H10, 0&) = 0 Then
    CreateObject("Scripting.FileSystemObject").MoveFile sTmpPath, sSave
    MsgBox "Finish"
  End If
End Sub
Tôi vừa thí nghiệm xong, không có vấn đề gì cả
 
Lần chỉnh sửa cuối:
Để đơn giản hóa vấn đề, tôi có cách này:
- Download file về 1 Temp Folder
- Dời file từ Temp Folder đến folder ta cần
Tôi vừa thí nghiệm xong, không có vấn đề gì cả
Thưa thầy nếu thầy tải về Temp Folder và Dời file từ Temp Folder đến folder ta cần thì chắc thời gian sẽ tốn thêm chút ít vậy nếu. Em tải file có dung lượng hơi lớn một chút và tải nhiều file lần lượt theo nhau chắc sẽ chậm!
 
Thưa thầy nếu thầy tải về Temp Folder và Dời file từ Temp Folder đến folder ta cần thì chắc thời gian sẽ tốn thêm chút ít vậy nếu. Em tải file có dung lượng hơi lớn một chút và tải nhiều file lần lượt theo nhau chắc sẽ chậm!
Dung lượng lớn là lớn cở bao nhiêu?
Đừng nói là bạn định viết chương trình "thay thế" cho Internet Download Manager nha!
Dùng code VB để download file, cùng lắm cũng chỉ vài tấm hình chơi thôi (phục vụ nhu cầu gì đó) chứ mà để download thật sự thì... ẹc... ẹc... có mà tới tết
 
Dung lượng lớn là lớn cở bao nhiêu?
Đừng nói là bạn định viết chương trình "thay thế" cho Internet Download Manager nha!
Dùng code VB để download file, cùng lắm cũng chỉ vài tấm hình chơi thôi (phục vụ nhu cầu gì đó) chứ mà để download thật sự thì... ẹc... ẹc... có mà tới tết
Dạ em dạo này có sở thích đọc truyện tranh trên mạng. Đặc biệt là trang: http://truyentranhnhanh.com/
lúc đầu em có định dùng IDM để tải nhưng tải chậm vì nó phải tìm hết các ảnh trên trang Web. Sau em dùng tay để kéo thả nhưng mỗi bộ truyện tính sơ qua phải kéo tới cỡ ngàn lần. Nản quá nên em chuyển sang viết code. Nay em đã viết xong file tải nhiều hình và nhiều chương chỉ bằng một vài cú Click chuột. Mà cỡ mỗi bộ khoảng trăm MB!!!!
 
Tại sao lại phải di chuyển file? Em thấy việc đưa vào temp rồi lại đưa ra thư mục đích có vẻ đường vòng không cần thiết? Hơn nữa nếu đưa vào temp thì cần phải dùng hàm API để nhận tên file do Windows chọn nếu không vô tình trừng với một file đang làm việc là lỗi ngay. Như ví dụ em làm chỉ cần hàm StrConv đổi chuỗi sang unicode là được.
 
Tại sao lại phải di chuyển file? Em thấy việc đưa vào temp rồi lại đưa ra thư mục đích có vẻ đường vòng không cần thiết? Hơn nữa nếu đưa vào temp thì cần phải dùng hàm API để nhận tên file do Windows chọn nếu không vô tình trừng với một file đang làm việc là lỗi ngay. Như ví dụ em làm chỉ cần hàm StrConv đổi chuỗi sang unicode là được.
Ý mình muốn nói rằng: Trong trường hợp mình không biết cái vụ Unicode kia thì ít ra mình cũng vẫn nghĩ được hướng đi khác (dù là đường vòng)
Chỉ vậy thôi!
Ẹc... Ẹc...
 
Ý mình muốn nói rằng: Trong trường hợp mình không biết cái vụ Unicode kia thì ít ra mình cũng vẫn nghĩ được hướng đi khác (dù là đường vòng)
Chỉ vậy thôi!
Ẹc... Ẹc...
Vâng lúc đầu không biết tải file theo đường dẫn Unicode em đã phải làm vậy. Nhưng em tải về một thư mục mình tạo ra rồi chuyển luôn cả thư mục
VD: Chap 1-10
 
Lần chỉnh sửa cuối:
Web KT

Bài viết mới nhất

Back
Top Bottom